<!-- 树组件 -->
<script lang="ts" setup>
import { ref, watch } from 'vue'
import type Node from 'element-plus/es/components/tree/src/model/node'

const emits = defineEmits(['nodeClick'])

const myProps = defineProps({
  nodeKey: {
    type: String,
    default: 'id'
  },
  // 是否多选
  multiple: {
    type: Boolean,
    default: false
  },
  // 属性映射
  props: {
    type: Object,
    default() {
      return {}
    }
  },
  // 是否父子不关联
  checkStrictly: {
    type: Boolean,
    default: true
  },
  // 是否显示勾选框
  showCheckbox: {
    type: Boolean,
    default: true
  },
  // 是否点击节点时选中节点
  checkOnClickNode: {
    type: Boolean,
    default: true
  },
  // 是否点击节点时展开
  expandOnClickNode: {
    type: Boolean,
    default: false
  },
  // 懒加载事件
  load: {
    type: Function,
    default: () => {}
  },
  // 搜索框高度
  searchHeight: {
    type: String,
    default: '32px'
  }
})

// 树ref
const treeRef = ref()
// 树数据过滤关键字
const filterText = ref('')

watch(filterText, (val) => {
  treeRef.value?.filter(val)
})

/**
 * 点击选择节点
 */
function handleNodeClick(curNode: any, allData: any) {
  // 多选
  if (myProps.multiple) {
    emits('nodeClick', allData)
  }
  // 单选
  else {
    if (allData.checkedKeys?.length) {
      treeRef.value?.setCheckedKeys([String(curNode[myProps.nodeKey])])
      emits('nodeClick', curNode)
    } else {
      treeRef.value?.setCheckedKeys([])
      emits('nodeClick', null)
    }
  }
}
/**
 * 树数据过滤方法
 */
function filterNodeFunc(text: string, data: any) {
  if (!text) {
    return true
  }
  const label = myProps.props.label ?? 'label'
  return data[label].includes(text)
}
/**
 * 懒加载方法
 */
function loadNodeEvt(node: Node, resolve: (data: any[]) => void) {
  let params = {}
  // 根节点加载
  if (node.level === 0) {
    params = { parentId: 1 }
  }
  // 子节点加载
  else {
    params = { parentId: node.data.id }
  }
  setTimeout(() => {
    myProps.load(node).then((resList: any[]) => {
      if (resList) {
        resolve(resList)
      }
    })
  }, 100)
}
</script>

<template>
  <div class="dui-tree-bg">
    <div class="dui-tree-search" :style="{ height: searchHeight }">
      <el-input v-model="filterText" placeholder="关键字过滤" clearable style="height: 100%" />
    </div>
    <div class="dui-tree-body" :style="{ height: `calc(100% - ${searchHeight})` }">
      <el-tree
        ref="treeRef"
        :nodeKey="nodeKey"
        :props="props"
        :checkStrictly="checkStrictly"
        :showCheckbox="showCheckbox"
        :checkOnClickNode="checkOnClickNode"
        :expandOnClickNode="expandOnClickNode"
        lazy
        :load="loadNodeEvt"
        :filter-node-method="filterNodeFunc"
        @check="handleNodeClick"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.dui-tree-bg {
  height: 100%;
  .dui-tree-search {
  }
  .dui-tree-body {
    margin-top: 4px;
    box-sizing: border-box;
    padding-bottom: 10px;
    overflow-y: auto;
  }
}
</style>
